<h2>模板引用(ms-include)</h2>
<p>稍为复杂一点的网站都是多个前端工程师合作而成，因此分工是必需的。简单一点的分工就是一个人负责一个频道，某个页面是由一个人全部做的；但如果涉及到一个页面非常复杂，需要多个人同时动工呢？于是到模板的出场时间了。</p>

<p>模板有两种，一种是嵌入到页面内的模板，一种是独立成子页面的模板。这两种avalon都支持。前者通常是使用type为浏览器无法识别的MIME类型的script标签，display:none的textarea标签或noscript标签（0.94后支持，建议使用它）作为模板容器，最近HTML5出了一个新的template标签，大家也不妨用一用。一般情况下，它是用于放置弹出层的内容。另一个模板，则需要通过AJAX请求来加载它们，它们适用范围更广，并且重用性更好。</p>

<p>对于页面内的模板，我们可以使用<strong>ms-include=&#8221;expr&#8221;</strong>绑定，对于独立于页面的模板，我们可以使用<strong>ms-include-src=&#8221;expr&#8221;</strong>绑定。ms-include要求对应一个<strong>ID</strong>（换言之，作为模板容器的script等标签必须指定ID），ms-include-src要求对应一个<strong>路径</strong>。需要注意的是ms-include或ms-include-src的属性值默认都是对应VM的一个属性，当作是一个变量，如果想直接使用字符串，那么需要使用<strong>双重引号</strong>。</p>

<xmp class="html">
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
        <script src="avalon.js"></script>
        <script>
            var model = avalon.define({
                $id: "test",
                content: "引入内部模板",
                name: "司徒正美",
                eee: "lala",
                change: function() {
                    model.eee = model.eee === "lala" ? "hehe" : "lala"
                }
            })
        </script>
    </head>
    <body ms-controller="test">
        <script type="avalon" id="tpl">
            here, {{ 3 + 6 * 5  }}
        </script>
        <script type="avalon" id="lala">
            <strong>{{name}}</strong>!!!
        </script>
        <script type="avalon" id="hehe">
           <em>{{content}}</em>!!!
        </script>
        <p>{{content}}<button ms-click="change" type="button">切换子模板</button></p>
        <div ms-include="'tpl'"></div><!--注意这里-->
        <div ms-include="eee"></div>
    </body>
</html>
</xmp>

<p><img src="../../assets/css/directives/include/1409809489146-include.gif" /></p>
<p>ms-include与ms-include-src的属性值可以添加插值表达式，见下面例子，不过注意需要打开服务器，因为用到AJAX请求。</p>

<p>有四个页面，一个主页面与三个独立的子模板，它们都放在一起，内容分别如下。</p>

<p>include.html</p>

<xmp class="html">
  <!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>ms-include</title>
        <script src="../avalon.js"></script>
        <script>
           var model = avalon.define({
                $id: "test",
                url: "Template1",
                name: "司徒正美",
                password: '12345678',
                array: [1, 2, 3, 4, 5, 6, 7],
                add: function(e) {
                    if (this.value &amp;&amp; e.which == 13) {//this为input元素
                        var a = this.value
                        model.array.push(a)
                        this.value = "";
                    }
                }
            })
        </script>
    </head>
    <body>
        <h3 style='text-align: center'>ms-include</h3>
        <div ms-controller="test">
            <select ms-duplex="url">
                <option>Template1</option>
                <option>Template2</option>
                <option>Template3</option>
            </select>
            <div ms-include-src="include{{url}}.html"></div>
        </div>
    </body>
</html>
</xmp>

<p>includeTemplate1.html</p>

<xmp class="html">
  <h1>这是模板1</h1>
<p>生成于{{ new Date | date("yyyy MM dd:HH:mm:ss")}}</p>
<p>生成于{{ "2011/07/08" | date("yyyy MM dd:HH:mm:ss")}}</p>
<p>生成于{{ "2011-07-08" | date("yyyy MM dd:HH:mm:ss")}}</p>
<p>生成于{{ "01-10-2000" | date("yyyy MM dd:HH:mm:ss")}}</p>
<p>生成于{{ "07 04,2000" | date("yyyy MM dd:HH:mm:ss")}}</p>
<p>生成于{{ "3 14,2000" | date("yyyy MM dd:HH:mm:ss")}}</p>
<p>生成于{{ 1373021259229 | date("yyyy MM dd:HH:mm:ss")}}</p>
<p>生成于{{ "1373021259229" | date("yyyy MM dd:HH:mm:ss")}}</p>
</xmp>
<p>值得注意的是，new Date可传的格式类型非常多，但不是所有浏览器都支持这么多，详看<a href="http://dygraphs.com/date-formats.html">这里</a>。</p>

<p>includeTemplate2.html</p>

<xmp class="html">
<script type="avalon" id='form'>
    <p>姓名：<input ms-duplex="name">{{name}}</p>
    <p>密码：<input type="password" ms-duplex="password"/>{{password}}</p>
</script>
<form ms-include="'form'" style='border:1px solid #666;background:sandybrown;padding:20px'>

</form>
</xmp>

<p>includeTemplate3.html</p>

<xmp class="html">
<ul ms-each-el="array">
    <li>第 {{$index+1}} 个元素: {{el}} <span ms-click="$remove">点我删除</span></li>
</ul>
<p>添加新元素 ，然后回车<input ms-keypress="add"></p>
</xmp>

<p><img src="../../assets/css/directives/include/1409809507647-include2.gif"  /></p>

<p>如果大家想在模板加载后，加工一下模板，可以使用data-include-loaded来指定回调的名字。</p>

<p>如果大家想在模板扫描后，隐藏loading什么的，可以使用data-include-rendered来指定回调的名字。</p>

<xmp class="html">
<!DOCTYPE html>
<html>
    <head>
        <title>ms-include相关实验</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <script src="avalon.js">
        </script>
        <script>
            avalon.define("test", function(vm) {
                vm.render = function(){
                    console.log("render")
                }
            })

        </script>
    </head>
    <body ms-controller="test" >
        <div ms-include-src="'temp.html'" data-include-rendered='render'></div>
    </body>
</html>
</xmp>

<p>temp.html</p>

<xmp class="html">
<!DOCTYPE html>
<html>
    <head>
        <title>TODO supply a title</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width">
        <script>
            console.log("----------")
        </script>
    </head>

    <body>
        <div>include content</div>
    </body>
</html>
</xmp>

<p><img src="../../assets/css/directives/include/1409810730376-include3.png" /></p>

<p>我们看<code>avalon.templateCache</code>，所有ms-include-src加载的模板都会缓存在这里，从而有效地减少请求数。
  并且这个东西还有一个额外的好处，我们的JS与CSS最终会压缩合并，对于这些模板我们也想把它们合并到JS文件里面，
  它就有用武之地了。这也是我们在第一节看到的那样，把requirejs加载回来的模板都放在<code>avalon.templateCache</code>里，
  与ms-include-src一起使用了。</p>

<xmp class="html">
<!DOCTYPE html>
<html>
    <head>
        <title>avalon.templateCache的应用</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width">
        <script src="avalon.js"></script>
        <script>
            avalon.templateCache["aaa.html"] = "<strong>dddddddddddd</strong>"
            avalon.templateCache["bbb.html"] = "<em>555555555555</em>"

            var model = avalon.define({
                $id: "test",
                adjust: function(tmpl) {
                    return tmpl +"  "+ (new Date - 0)
                },
                aaa: "aaa.html",
                change: function() {
                    model.aaa = model.aaa === "aaa.html" ? "bbb.html" : "aaa.html"
                }
            })
        </script>
    </head>
    <body ms-controller="test">
        <div ms-include-src="aaa" data-include-loaded="adjust"></div>
        <button type="button" ms-click="change">点我切换模板</button>
    </body>
</html>
</xmp>

<p><img src="../../assets/css/directives/include/1409812441030-include4.gif"  /></p>
<div class="bs-callout bs-callout-info" >
  <p>在avalon1.3.7中添加一个辅助指令data-include-replace，当其值为真，它就会加载模板后自动替代掉其原父容器节点。
  主页面</p>
</div>

<xmp class="html">
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>duplexHooks</title>
        <meta http-equiv="X-UA-Compatible" content="IE=8" />
        <script src="../avalon.modern.js"></script>
        <style>
            .bp{
                border: 1px  solid green;
            }
            .contain{
                border: 1px solid red;
            }
        </style>
        <script>
            var a = avalon.define({
                $id: "test",
                aaa: "aaa.html",
                change: function() {
                    a.aaa = a.aaa === "aaa.html" ? "bbb.html" : "aaa.html"
                }
            })

        </script>
    </head>
    <body ms-controller="test">
        <button type="button" ms-click="change">change</button>
        <div ms-include-src="'include2'+aaa" class="contain"></div>
        <div ms-include-src="'include2'+aaa" class="contain" data-include-replace="true"></div>
    </body>
</html>
</xmp>

<p>include2aaa.html</p>

<xmp class="html">
<div>xxxxxxxxxxxxx</div>
<div>yyyyyyyyyyyy</div>
</xmp>

<p>include2bbb.html</p>

<xmp class="html">
<p class="bp">aaaaaaaaaaa</p>
<p class="bp">bbbbbbbbbbb</p>
<p class="bp">ccccccccccc</p>
</xmp>

<p><img src="../../assets/css/directives/include/1414724133046-include-replace.gif" /></p>
<p>我们结合data-include-rendered, ms-repeat, ms-include实现一个网易式的评论呈现树吧</p>
<xmp class="html">
<!DOCTYPE html>
<html>
    <head>
        <title>TODO supply a title</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width">
        <script src="avalon.js"></script>
        <style>
            .level_even {
                background: #ccc;
            }
            .level_odd {
                background: #fff;
            }
        </style>
        <script>
            var array = [{children: [], author: "第一层a"}, {children: [], author: "第一层b"}];
            array[0].children.push({children: [], author: "第二层a"}, {children: [], author: "第二层b"})
            array[0].children[0].children.push({children: [], author: "第三层a"}, {children: [], author: "第三层b"})
            array[0].children[0].children[0].children.push({children: [], author: "第四层a"}, {children: [], author: "第四层b"}, {children: [], author: "第四层c"})
            var vm = avalon.define({
                $id: "test",
                aaa: "通过ms-repeat, ms-include实现树",
                array: array,
                addClass: function() {
                    var level = 0
                    var parent = this.parentNode
                    do {
                        if (parent.tagName == "UL") {
                            level++
                        }
                        if (parent.tagName === "BODY") {
                            break
                        }
                    } while (parent = parent.parentNode)
                    avalon(this).addClass("level_" + level)
                    avalon(this).addClass(level % 2 === 0 ? "level_even" : "level_odd")
                }
            })


        </script>
    </head>
    <body ms-controller="test">
        <h2>{{aaa}}</h2>
        <script type="avalon" id="comments">
            <ul>
            <li ms-repeat="el.children" >
            {{el.author}}
            <div ms-if="el.children.size()" ms-include="'comments'" data-include-rendered='addClass' > </div>
            </li>
            </ul>
        </script>
        <div class='level_0 level_even'>
            <ul>
                <li ms-repeat="array">
                    {{el.author}}
                    <div ms-if="el.children.size()" ms-include="'comments'" data-include-rendered='addClass'></div>
                </li>
            </ul>
        </div>
    </body>
</html>

</xmp>
<p><img src="../../assets/css/directives/include/include2.png"  /></p>
<p>avalon1.4.2中，添加了data-include-cache="true"辅助指令，它会保存之前的模板被扫描后的DOM节点。</p>
<xml class="html">
<!DOCTYPE html>
<html>
    <head>
        <title>data-include-cache="true"</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width">
        <script src="avalon.js"></script>
        <script>
            var vm = avalon.define({
                $id: "test",
                aaa: "",
                changeA: function () {
                    vm.aaa = "aaa"
                },
                changeB: function () {
                    vm.aaa = "bbb"
                },
                changeC: function () {
                    vm.aaa = "ccc"
                }
            })
        </script>
        <script type="avalon" id="aaa">
            <h2>这是模板1</h2>
    {{new Date - 0}}
        </script>
        <script type="avalon" id="bbb">
          <h2>这是模板2</h2>
  {{new Date - 0}}
        </script>
        <script type="avalon" id="ccc">
            <h2>这是模板3</h2>
    {{new Date - 0}}
        </script>
    </head>
    <body>
        <div ms-controller="test">
            <div ms-include="aaa" data-include-cache="true">准备加载模块....</div>
            <p>
                <button type="button" ms-click="changeA">aaa</button>
                <button type="button" ms-click="changeB">bbb</button>
                <button type="button" ms-click="changeC">ccc</button>
            </p>
        </div>
    </body>
</html>
</xmp>
